<script>
import OperatingCateNode from "./node/OperatingCateNode.vue";
import OperatingRoomNode from "./node/OperatingRoomNode.vue";
import OperatingPatientNode from "./node/OperatingPatientNode.vue";
import OperatingDockerNode from "./node/OperatingDockerNode.vue";
import OperatingEmptyNode from "./node/OperatingEmptyNode.vue";
import OperatingGroupNode from "./node/OperatingGroupNode.vue";
import { ElsCollapse } from "./collapse";
export default {
  name: "CollapseWrapper",
  inject: ["getManager", "getIsShow", "foldIdsInfo"],
  props: {
    type: {
      type: String,
      required: true,
    },
    operatingShowType: {
      type: String,
      default: () => "link",
    }, // link | 'fix'

    config: {
      type: Object,
      default: () => {
        return {
          idKey: "id",
          pidKey: "pid",
        };
      },
    },
    list: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      activeNames: [],
      scrollOffset: null,
      activedId: "",
      isTransitionRunning: false, // patient fix 模式 展开/折叠 动画状态， group 动态计算高度要用
    };
  },
  computed: {
    dataList() {
      return [
        ...this.list.filter((item) => {
          let id = item[this.config.idKey || "id"];
          return !this.getIsShow(this.type, id);
        }),
      ];
    },
  },
  watch: {
    activedId(val, oldVal) {
      let activedId = val;
      let oldActivedId = oldVal;
      this.$emit("activedChange", val, this.type);
      if (this.type === "operating" && this.operatingShowType !== "group") {
        [activedId, oldActivedId] = [val, oldVal].map((item) => {
          let parentNodeId =
            item && this.getManager().getPatientNodeById(item)?.id;
          return parentNodeId && `${parentNodeId}_group`;
        });
        // 点击分组内的某一个时，pid 不变 -> 分组id 不变
        if (activedId === oldActivedId) {
          return;
        }
      }
      this.$nextTick(() => {
        this.getManager().updateHighlight(
          [activedId, oldActivedId].filter((item) => !!item)
        );
      });
    },
  },

  methods: {
    getComponentName(type) {
      switch (type) {
        case "opcategory":
          return "operating-cate-node";
        case "room":
          // return "operating-cate-node";
          return "operating-room-node";
        case "docker":
          return "operating-docker-node";
        case "operating":
          return "operating-patient-node";
        default:
          return "operating-empty-node";
      }
    },
    nodeClickHandler(id, flag = "auto") {
      if (this.activedId === id) {
        this.activedId = null;
        this.activeNames = [];
      } else {
        this.activedId = id;
        if (flag === "auto") {
          if (!this.activeNames.includes(id)) {
            this.activeNames = [];
          }
        } else {
          this.activeNames = flag === true ? [id] : [];
        }
      }
    },
    toggleFold(id) {
      this.$emit("toggleFold", this.type, id);
    },
    collapseTrans(type) {
      let execFn = () => {
        if (this.operatingShowType !== "fix" || this.type !== "operating") {
          this.timer = setTimeout(() => {
            this.getManager()?.updateEdges();
            execFn();
          }, 25);
        }
      };
      if (type === "beforeEnter" || type === "beforeLeave") {
        clearInterval(this.timer);
        this.isTransitionRunning = true;
        execFn();
      } else if (type === "afterLeave" || type === "afterEnter") {
        clearInterval(this.timer);
        this.isTransitionRunning = false;
      }
    },
    mousewheelHandler() {
      let { scrollTop, scrollLeft } = this.$refs.listWrap;
      this.scrollOffset = {
        scrollTop,
        scrollLeft,
      };
      this.$nextTick(() => {
        this.getManager().updateEdges();
      });
    },
    transitionEnter() {
      clearTimeout(this.entertimer);
      let execFn = () => {
        this.entertimer = setTimeout(() => {
          this.getManager()?.updateEdges();
          execFn();
        }, 15);
      };
      execFn();
    },
    transitionAfterEnter() {
      setTimeout(() => {
        clearTimeout(this.entertimer);
      }, 20);
    },
    transitionLeave() {
      clearTimeout(this.entertimer);
      let execFn = () => {
        this.entertimer = setTimeout(() => {
          this.getManager()?.updateEdges();
          execFn();
        }, 15);
      };
      execFn();
    },
    transitionAfterLeave() {
      setTimeout(() => {
        clearTimeout(this.entertimer);
      }, 20);
    },
  },
  mounted() {
    this.activedId =
      this.type === "operating"
        ? this.dataList[0]?.list?.[0]?.[this.config.idKey || "id"]
        : this.dataList[0]?.id;
  },

  components: {
    OperatingCateNode,
    OperatingRoomNode,
    OperatingPatientNode,
    OperatingDockerNode,
    OperatingGroupNode,
    OperatingEmptyNode,
    ElsCollapse,
  },
};
</script>
<template>
  <div class="collapse-wrap">
    <els-collapse
      :accordion="true"
      v-model="activeNames"
      @transitions="collapseTrans"
    >
      <div
        :class="['node-container', type]"
        ref="listWrap"
        @scroll="mousewheelHandler"
      >
        <transition-group
          tag="div"
          name="slider"
          class="node-list-wrap"
          v-if="type === 'operating'"
          @enter="transitionEnter"
          @afterEnter="transitionAfterEnter"
          @leave="transitionLeave"
          @afterLeave="transitionAfterLeave"
        >
          <operating-group-node
            ref="group"
            v-for="groupList in dataList"
            :id="groupList.id"
            :pid="groupList.pid"
            :activedId="activedId"
            :key="groupList.id"
            :data="groupList.list"
            :config="groupList.config"
            :showType="operatingShowType"
            :isTransitionRunning="isTransitionRunning"
            :scrollOffset="scrollOffset"
            @clickedHandler="nodeClickHandler"
          >
          </operating-group-node>
        </transition-group>
        <transition-group
          v-else
          tag="div"
          name="slider"
          :class="['node-list-wrap', type]"
          @enter="transitionEnter"
          @afterEnter="transitionAfterEnter"
          @leave="transitionLeave"
          @afterLeave="transitionAfterLeave"
        >
          <component
            v-for="item in dataList"
            ref="nodeList"
            class="card-node"
            :is="getComponentName(type)"
            :id="item[config.idKey || 'id']"
            :pid="item[config.pidKey || 'pid']"
            :activedId="activedId"
            :key="item[config.idKey || 'id']"
            :data="item"
            :fold="
              !!foldIdsInfo.find((it) => it.id === item[config.idKey || 'id'])
            "
            @clickedHandler="nodeClickHandler"
            @toggleFold="toggleFold"
          />
        </transition-group>
      </div>
    </els-collapse>
  </div>
</template>
<style scoped lang="less">
.collapse-wrap {
  height: 100%;

  .node-container {
    padding: 8px 7px 0px 8px;
    height: 100%;
    overflow: hidden;
    overflow-y: auto;
    overflow-y: overlay;
    scrollbar-gutter: stable;
    position: relative;
    &::-webkit-scrollbar {
      display: block;
      width: 0;
      height: 4px;
      background: transparent;
    }
    &::-webkit-scrollbar-corner {
      background-color: transparent;
    }
    &::-webkit-scrollbar-thumb {
      background: rgba(0, 0, 0, 0.2);
      border: none;
      border-radius: 4px;
    }
    &::-webkit-scrollbar-track {
      background: transparent;
    }
    &.operating {
      padding-top: 0;
      overflow: auto;
      overflow: overlay;
    }
    .node-list-wrap {
      .card-node {
        margin-bottom: 10px;
        overflow: visible;

        ::v-deep {
          .els-collapse-item {
            border-radius: 4px;
            outline: 1px solid #d8d8d8;
            outline-offset: -1px;

            &:hover {
              box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
            }

            &:last-child {
              margin-bottom: 0;
            }
          }
          &.actived .sch-dot.--right {
            color: #1677ff;
          }
        }
      }

      ::v-deep .sch-dot {
        transition: background 0.3s linear;
        position: absolute;
        top: 50%;
        margin-top: -6px;
        width: 12px;
        height: 12px;
        display: flex;
        align-items: center;
        justify-content: center;
        background: #fff;
        z-index: 999;

        &.--left {
          width: 0;
          height: 0;
          left: -9px;
        }

        &.--right {
          cursor: pointer;
          color: rgba(217, 217, 217, 1);
          right: -6px;
        }
      }
    }
  }
  .slider-enter-active {
    transition: all 0.5s;
  }
  .slider-leave-active {
    transition: all 0.5s;
    min-height: 0 !important;
    padding-top: 0 !important;
  }
  .slider-enter {
    opacity: 0;
  }
  .slider-leave {
    height: 200px;
  }
  .slider-leave-to {
    opacity: 0;
    height: 0;
  }
  .slider-move {
    transition: transform 0.3s;
  }
}
</style>
